<?php
/**
 * Zephyr Framework
 *
 * LICENSE
 *
 * This source file is subject to the new BSD license that is bundled
 * with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://code.google.com/p/zephyr-framework/wiki/License
 *
 * @category   Zephyr
 * @package    Zephyr_Validate
 * @copyright  Copyright (c) 2008 Peo Development Group (http://peo.com.pl)
 * @license    http://code.google.com/p/zephyr-framework/wiki/License     New BSD License
 * @version    $Id: Base.php 9 2008-07-23 17:33:56Z w.naruniec $
 */


/**
 * @see Zephyr_Service_SugarCrm_Decorator
 */
require_once 'Zephyr/Service/SugarCrm/Decorator.php';


/**
 * @category   Zephyr
 * @package    Zephyr_Service
 * @subpackage SugarCrm
 * @copyright  Copyright (c) 2008 Peo Development Group (http://peo.com.pl)
 * @license    http://code.google.com/p/zephyr-framework/wiki/License     New BSD License
 */
class Zephyr_Service_SugarCrm_Base
{
    /**
     * Configuration options
     * @param array
     */
    protected $_options = array('username' => null,
                                'password' => null,
                                'client'   => null,
                                'options'  => null,
                                'headers'  => null,
                                'wsdl'     => null,
                                'uri'      => null,
                                'location' => null);

    protected $_id = null;
                                
    /**
     * Output headers returned by the last call to SOAPClient->__soapCall()
     * @param array
     */
    protected $_outputHeaders = array();

    /**
     * Class constructor
     *
     * @param  array  $options  Key/value pair options
     * @throws Zephyr_Service_SugarCrm_Exception
     */
    public function __construct($options = array())
    {
        if (!extension_loaded('soap')) {
            /**
             * @see Zephyr_Service_SugarCrm_Exception
             */
            require_once 'Zephyr/Service/SugarCrm/Exception.php';
            throw new Zephyr_Service_SugarCrm_Exception('SOAP extension is not enabled');
        }

        $this->_options  = array_merge($this->_options, $options);

        $this->_options['options'] = array(
            'uri' => $options['uri'],
            'location' => $options['location']
        );

        $this->_initSoapHeaders();
        $this->_initSoapClient();

        $this->_loginSoapClient();
    }

    /**
     * Proxy method calls to the SOAPClient instance, transforming method
     * calls and responses for convenience.
     *
     * @param  string  $method  Method name
     * @param  array   $params  Parameters for method
     * @return mixed            Result
     * @throws Zephyr_Service_SugarCrm_Exception
     */
    public function __call($method, $params)
    {
        // prepare method name and parameters for soap call
        list($method, $params) = $this->_transformCall($method, $params);

        $params = isset($params[0]) ? $params[0] : array($params);

        // make soap call, capturing the result and output headers
        try {
            $result = $this->_options['client']->__soapCall($method, $params, $this->_options['options'], $this->_options['headers'], $this->_outputHeaders);
        } catch (Exception $e) {
            $message = get_class($e) . ': ' . $e->getMessage();
            /**
             * @see Zephyr_Service_SugarCrm_Exception
             */
            require_once 'Zephyr/Service/SugarCrm/Exception.php';
            throw new Zephyr_Service_SugarCrm_Exception($message, $e->getCode());
        }

        // transform/decorate the result and return it
        $result = $this->_transformResult($result, $method, $params);

        if (isset($result->error->number) && $result->error->number > 0) {
            /**
             * @see Zephyr_Service_SugarCrm_Exception
             */
            require_once 'Zephyr/Service/SugarCrm/Exception.php';
            throw new Zephyr_Service_SugarCrm_Exception('Sugar_Crm: ' . $result->error->description,
                                                        $result->error->number);
        }

        return $result;
    }

    public function getId()
    {
    	return $this->_id;
    }
    
    /**
     * Initialize the SOAPClient instance
     *
     * @return void
     */
    protected function _initSoapClient()
    {
        if (! isset($this->_options['options'])) {
            $this->_options['options'] = array();
        }

        if (! isset($this->_options['client'])) {
            $this->_options['client'] = new SoapClient(null,
                                                       $this->_options['options']);
        }
    }

    /**
     * Initialize the headers to pass to SOAPClient->__soapCall()
     *
     * @return void
     * @throws Zephyr_Service_SugarCrm_Exception
     */
    protected function _initSoapHeaders()
    {
        // validate headers
        if (isset($this->_options['headers'])) {
            if (! is_array($this->_options['headers'])) {
                $this->_options['headers'] = array($this->_options['headers']);
            }

            foreach ($this->_options['headers'] as $header) {
                if (! $header instanceof SoapHeader) {
                    /**
                     * @see Zephyr_Service_SugarCrm_Exception
                     */
                    require_once 'Zephyr/Service/SugarCrm/Exception.php';
                    throw new Zephyr_Service_SugarCrm_Exception('Header must be instance of SoapHeader');
                }
            }
        } else {
            $this->_options['headers'] = array();
        }
    }
    
    /**
     * Login into Web Service
     *
     * @return void
     */
    protected function _loginSoapClient()
    {
        $result = $this->login(array(
            'user_auth' => array(
                'user_name' => $this->_options['username'],
                'password' => md5($this->_options['password']),
                'version' => '.01',
            ),
        ));

        $this->_id = $result->id;
    }

    /**
     * Transform a method name or method parameters before sending them
     * to the remote service.  This can be useful for inflection or other
     * transforms to give the method call a more PHP-like interface.
     *
     * @see    __call()
     * @param  string  $method  Method name called from PHP
     * @param  mixed   $param   Parameters passed from PHP
     * @return array            [$method, $params] for SOAPClient->__soapCall()
     */
    protected function _transformCall($method, $params)
    {
        return array($method, $params);
    }

    /**
     * Transform the result returned from a method before returning
     * it to the PHP caller.  This can be useful for transforming
     * the SOAPClient returned result to be more PHP-like.
     *
     * The $method name and $params passed to the method are provided to
     * allow decisions to be made about how to transform the result based
     * on what was originally called.
     *
     * @see    __call()
     * @param  $result  Raw result returned from SOAPClient_>__soapCall()
     * @param  $method  Method name that was passed to SOAPClient->__soapCall()
     * @param  $params  Method parameters that were passed to SOAPClient->__soapCall()
     * @return mixed    Transformed result
     */
    protected function _transformResult($result, $method, $params)
    {
        $resultObjectName = "{$method}Result";
        if (isset($result->$resultObjectName)) {
            $result = $result->$resultObjectName;
        }
        if (is_object($result)) {
            $result = new Zephyr_Service_SugarCrm_Decorator($result, $resultObjectName);
        }
        return $result;
    }

    /**
     * Get the WSDL URL for this service.
     *
     * @return string
     */
    public function getWsdl()
    {
        return $this->_options['wsdl'];
    }

    /**
     * Get the SOAP Client instance for this service.
     */
    public function getSoapClient()
    {
        return $this->_options['client'];
    }
}
